﻿using Com.JunCaiSoft.Common.AssistClass;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Com.JunCaiSoft.Common.Verification
{
    public class OrgnizationCode
    {
        private static string orgnizationCode { get; set; }
        private OrgnizationCode(string inputOrgnizationCode)
        {
            orgnizationCode = inputOrgnizationCode;
            RegularExpression();
            OrgnizationCodeCheckResult();
        }

        private void RegularExpression()
        {
            if (!Regex.IsMatch(orgnizationCode, @"(^\d{8}[X?]|\d{1}$)"))
            {
                throw new Exception("输入的身份号码有误！");
            }
        }

        private void OrgnizationCodeCheckResult()
        {
            if (orgnizationCode.Length != 9)
            {
                throw new Exception("组织机构代码位数不正确！");
            }
            var orgnization = orgnizationCode.Substring(0, 8);
            var orgnizationCheckCode = orgnizationCode.Substring(8, 1);
            int sum = 0;
            for (int i = 0; i < orgnization.Length; i++)
            {
                sum += OrgnizationCodeHeavy(orgnization.Substring(i, 1), i + 1);
            }
            var computeResult = 11 - sum % 11;
            string resultChar = null;
            if (computeResult == 10)
            {
                resultChar = "X";
            }
            else if (computeResult == 11)
            {
                resultChar = "0";
            }
            else
            {
                resultChar = OrgnizationResultChange(computeResult);
            }
            if (resultChar == orgnizationCheckCode)
            {
                orgnizationCode = orgnizationCode;
            }
            else
            {
                throw new Exception("组织机构代码错误！");
            }
        }

        private string OrgnizationResultChange(int inputNum)
        {
            var a = inputNum + 55;
            if (a > 64 && a < 91)
            {
                return (ASCIIExchange.Chr(inputNum + 55));
            }
            else if (inputNum + 48 > 47 && inputNum + 48 < 58)
            {
                return inputNum.ToString();
            }
            else
            {
                throw new Exception("输入字符错误！");
            }
        }

        private int OrgnizationCodeHeavy(string input, int position)
        {
            if (input.Length > 1)
            {
                throw new Exception("传入字符位数不对！");
            }
            int rights;
            switch (position)
            {
                case 1: rights = 3; break;
                case 2: rights = 7; break;
                case 3: rights = 9; break;
                case 4: rights = 10; break;
                case 5: rights = 5; break;
                case 6: rights = 8; break;
                case 7: rights = 4; break;
                case 8: rights = 2; break;
                default: rights = 0; break;
            }
            return OrgnizationCharChange(input) * rights;
        }

        private int OrgnizationCharChange(string input)
        {
            var a = ASCIIExchange.Asc(input.ToUpper());
            if (a > 64 && a < 91)
            {
                return ASCIIExchange.Asc(input) - 55;
            }
            else if (a > 47 && a < 58)
            {
                return Int32.Parse(input);
            }
            else
            {
                throw new Exception("输入字符错误！");
            }
        }
        /// <summary>
        /// 根据前8位可以计算出组织机构代码证最后一位校验位
        /// </summary>
        /// <param name="inputOrgnizationCode"></param>
        /// <returns></returns>

        public static string CheckOrgnizationCode(string inputOrgnizationCode)
        {
            if (inputOrgnizationCode.EndsWith("?"))
            {
                throw new Exception("不允许输入其他字符！");
            }
            if (inputOrgnizationCode.Length == 8)
            {
                orgnizationCode += "?";
            }
            new OrgnizationCode(inputOrgnizationCode);
            return orgnizationCode;
        }
    }
}
